ADV-206 不大的数(高精度乘法)

问题描述
  在当今的大数据时代,超大数的高精度计算已经成为众多领域的热门研究之一。现在T校也想在此领域有所造诣已造福于全社会,然而由于时间有限,所以短时间内难以找出大数计算的通用算法,于是学校找到了同学中的“神霸”——你来帮忙,并仅要求你能在数并不算大的时候给出结果。又出于某种特殊需要,也并不要求你给出数的全部结果,而只是要求结果的前10位(注意不是后10位),并考虑到2的幂次的特殊性和典型性,所以要你计算的数均为2的幂次。
输入格式
  一个自然数n。
输出格式
  2的n次幂的前10位。
样例1 输入
  60
样例1 输出
  1152921504
样例2 输入
  60000
样例2 输出
  6305794870
数据规模和约定
  0<=n<=10000000
注释
  =。=


PS:
一、2^i,当i>34时,会超过10位数字,2^40有13位数字
二、B=2^i,当i>34且i%10==0时,B=B/1000,
即2^10==1024;1024/1000=1.024;
1.024^97.1==10.0028968...
B*2^10/1000==B*1.024
(B*1.024)^97.1/10.0028968...=B=^97.1
三、每乘971个2,要/10

例:
# include <stdio.h>
 # include <string.h>  // 调用strlen函数的头文件
int main(void) {
    char a1[250], b1[250];  // 先定义两个字符数组,用于存储两个较多位数的乘数
    int a[250], b[250], c[500] = {0};  // 再定义三个数组,前两个用于接收字符数组里的数字各个位的数值,最后一个用于存储最终结果的各个位的数值
    int len1, len2, len;  // 前两个分别表示字符数组a1,b1的实际长度,最后一个表示两个字符数组实际长度之和
    scanf("%s%s", a1, b1);  // 对两个字符数组进行赋值
    len1 = strlen(a1);  // 将字符串a1的长度赋给len1,用于数组的赋值
    len2 = strlen(b1);  // 将字符串b1的长度赋给len2, 用于数组的赋值
    len = len1 + len2;  // 将两字符串实际长度之和赋给len
    for (int i = 0; i < len1; i++)   // 用for循环,实现字符数组a1内数字向数组转移
        a[i] = a1[len1-1-i] - '0';
    /* 不过,字符数组内的数字与数组内数字顺序相反,这与乘法原理有关,根据ASCII,字符数组内的数字要转化成实际的数字,就要减去48,因为‘0’的ASCII码恰好是48,所以将字符数组元素-‘0’以实现转化 */
    for (int j = 0; j < len2; j++) // 用for循环,实现字符数组b1内数字向数组转移
        b[j] = b1[len1-1-j] - '0';
    for (int i = 0; i < len1; i++)  // 接下来这两个嵌套的for循环便是高精度乘法的核心
        for (int j = 0; j < len2; j++) { // 此处这短短三步需要结合乘法原理理解,用文字很难表达
            c[i+j] += a[i]*b[j];  // 数字的其中一位与另一数字其中一位相乘,先不考虑进位情况
            c[i+j+1] += (c[i+j]) / 10;  // 除以10的作用便是判断进多少(注意是c[i+j])
            c[i+j] = c[i+j] % 10;  // 进位结束以后该数位便只去各位,故将其取余取余数(注意是c[i+j])
        }  // 此处第一、第二个式子用+=,原因可根据乘法原理解释,第三个式子无需+=,原因是取该位数总值的个位即可
    if (c[len-1] == 0)  //  此处是判断输出的第一个数位是否为0,若为0,忽略该位数,即总长减去1
        len--;
    for (int i = len-1; i >= 0; i--) // 倒着输出数组内的数字,得到最终结果
        printf("%d", c[i]);
    return 0;
}

PPS:
1.&n
2.ans = ans * 2;
3.ans > 1000000000000000000(18位)
4.%lld
#include
    
    
     
     

int main(){
	int n,i,j;
	long long ans = 1;
        scanf("%d",&n);
	
	for(i=0;i
     
     
      
       1000000000000000000){
			ans /= 10;
		}
		
	}
	while(ans > 10000000000){
		ans /= 10;
	}
	
	printf("%lld",ans);
	return 0;
} 



     
     
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值